/**
 * Copyright 2010 Victor Egea Hernando
 *
 * RockScript is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, version 3 of the License.
 *
 * RockScript is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with RockScript.  If not, see <http://www.gnu.org/licenses/>.
 */
#include "pjit_block.h"
#include <cstdlib>

namespace pjit{

pjit_block::pjit_block( void ){
	_block = _pointer = 0;
	_back_asm = false;
	_size = 0;
}

pjit_block::~pjit_block(){
	// free memory
	if( _block ){
		std::free( _block );
	}
}

bool pjit_block::ready( void ) const{
	return( _size );
}

uint32 pjit_block::size( void ) const{
	return ( _size );
}

uint32 pjit_block::gap( void ) const{
	return ( _size - static_cast<uint32>( _pointer - _block ) );
}

uint32 pjit_block::offset( void ) const{
	return( static_cast<uint32>( _pointer - _block ) );
}

void pjit_block::skip( uint32 bytes ){
	_pointer += bytes;
}

void pjit_block::go_to( uint32 offset ){
	_pointer = _block + offset;
}

std::ostream &pjit_block::asm_os( void ){
	return( _asms );
}

std::string pjit_block::asm_str( void ) const{
	return( _asms.str() );
}

void pjit_block::set_back_asm( bool block_asm ){
	_back_asm = block_asm;
}

bool pjit_block::back_asm( void ) const{
	return( _back_asm );
}

void pjit_block::reserve( uint32 bytes ){
	if( !_block && bytes ){
		// alloc memory
		_block = _pointer = reinterpret_cast<uint8*>( std::malloc( bytes ) );
		_size  = bytes;
		// PAX: mprotect()?
	}else if( _size < bytes ){
		// realloc data
		uint32 offset = static_cast<uint32>( _pointer - _block );
		_block = reinterpret_cast<uint8*>( std::realloc( _block, bytes ) );
		_pointer = _block + offset;
		// PAX: mprotect()?
	}
}

void pjit_block::push_1byte ( uint8 data ){
	_pointer[0] = data; _pointer++;
}

void pjit_block::push_2bytes( uint16 data ){
	uint16 *npointer = reinterpret_cast<uint16 *>( _pointer );
	npointer[0] = data; _pointer += 2;
}

void pjit_block::push_4bytes( uint32 data ){
	uint32 *npointer = reinterpret_cast<uint32 *>( _pointer );
	npointer[0] = data; _pointer += 4;
}

void pjit_block::push_8bytes( uint64 data ){
	uint64 *npointer = reinterpret_cast<uint64 *>( _pointer );
	npointer[0] = data; _pointer += 8;
}

}; // namespace pjit
